<!--
 * @Description: 文件预览组件
 * @Author: huguodong
 * @Date: 2023-12-15 15:45:10
!-->
<template>
  <el-dialog v-model="dialogVisible" :title="fileInfo.name" destroy-on-close draggable width="35%">
    <div class="preview-container">
      <!-- 图片预览 -->
      <div v-if="isImage" class="image-preview">
        <el-image :preview-src-list="[previewUrl]" :src="previewUrl" fit="contain" />
      </div>

      <!-- 视频预览 -->
      <div v-else-if="isVideo" class="video-preview">
        <video :src="previewUrl" controls width="100%"></video>
      </div>

      <!-- 音频预览 -->
      <div v-else-if="isAudio" class="audio-preview">
        <audio :src="previewUrl" controls></audio>
      </div>

      <!-- PDF预览 -->
      <div v-else-if="isPdf" class="pdf-preview">
        <iframe :src="previewUrl" height="600px" width="100%"></iframe>
      </div>

      <!-- 文本预览 -->
      <div v-else-if="isText" class="text-preview">
        <el-input v-model="textContent" :rows="20" readonly type="textarea" />
      </div>

      <!-- 不支持预览 -->
      <div v-else class="no-preview">
        <el-empty description="该文件类型不支持在线预览">
          <el-button type="primary" @click="handleDownload">下载文件</el-button>
        </el-empty>
      </div>
    </div>

    <template #footer>
      <el-button @click="dialogVisible = false">关闭</el-button>
      <el-button type="primary" @click="handleDownload">下载</el-button>
    </template>
  </el-dialog>
</template>

<script lang="ts" name="filePreview" setup>
import { ElMessage } from "element-plus";
import { useUserStore } from "@/stores/modules";

const userStore = useUserStore();

// 对话框显示
const dialogVisible = ref(false);
// 文件信息
const fileInfo = ref<any>({
  id: "",
  name: "",
  suffix: "",
  downloadPath: "",
  thumbnail: ""
});

// 文本内容
const textContent = ref("");

// 预览URL - 优先使用thumbnail(base64),其次使用downloadPath
const previewUrl = computed(() => {
  // 如果有thumbnail(图片的base64缩略图),直接使用
  if (fileInfo.value.thumbnail) {
    return fileInfo.value.thumbnail;
  }
  // 否则使用downloadPath(网络路径)
  const path = fileInfo.value.downloadPath || "";
  // 如果是本地文件路径,返空(无法直接预览)
  if (path.startsWith("file:///")) {
    return "";
  }
  return path;
});

// 获取文件后缀
const fileExt = computed(() => {
  const suffix = fileInfo.value.suffix || "";
  return suffix.toLowerCase().replace(".", "");
});

// 判断文件类型
const isImage = computed(() => {
  const imageExts = ["jpg", "jpeg", "png", "gif", "bmp", "webp", "svg"];
  return imageExts.some(ext => fileExt.value.includes(ext));
});

const isVideo = computed(() => {
  const videoExts = ["mp4", "webm", "ogg", "avi", "mov"];
  return videoExts.some(ext => fileExt.value.includes(ext));
});

const isAudio = computed(() => {
  const audioExts = ["mp3", "wav", "ogg", "flac"];
  return audioExts.some(ext => fileExt.value.includes(ext));
});

const isPdf = computed(() => {
  return fileExt.value.includes("pdf");
});

const isText = computed(() => {
  const textExts = ["txt", "json", "xml", "html", "css", "js", "ts", "md"];
  return textExts.some(ext => fileExt.value.includes(ext));
});

/**
 * 打开预览
 */
async function onOpen(file: any) {
  dialogVisible.value = true;
  fileInfo.value = file;

  // 如果是文本文件，加载内容
  if (isText.value && previewUrl.value) {
    try {
      const response = await fetch(previewUrl.value);
      textContent.value = await response.text();
    } catch (error) {
      ElMessage.error("加载文件内容失败");
    }
  }
}

/**
 * 下载文件
 */
async function handleDownload() {
  try {
    const { accessToken } = userStore;
    if (!accessToken) {
      ElMessage.error("未登录,请先登录");
      return;
    }

    if (!fileInfo.value.id) {
      ElMessage.warning("文件ID不存在");
      return;
    }

    const response = await fetch(`/api/sys/dev/file/download?id=${fileInfo.value.id}`, {
      method: "GET",
      headers: {
        Authorization: `Bearer ${accessToken}`
      }
    });

    if (!response.ok) {
      ElMessage.error("下载失败");
      return;
    }

    // 获取文件blob
    const blob = await response.blob();
    // 创建下载链接
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = fileInfo.value.name || "download";
    document.body.appendChild(a);
    a.click();
    // 清理
    window.URL.revokeObjectURL(url);
    document.body.removeChild(a);
  } catch (error) {
    ElMessage.error("下载失败");
  }
}

// 暴露方法
defineExpose({ onOpen });
</script>
<style lang="scss" scoped>
.preview-container {
  min-height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;

  .image-preview {
    width: 70%;
    text-align: center;

    :deep(.el-image) {
      width: 100%;
      height: auto;
    }

    :deep(.el-image__inner) {
      width: 100%;
      height: auto;
      object-fit: contain;
    }
  }

  .video-preview,
  .audio-preview {
    width: 100%;
  }

  .pdf-preview {
    width: 100%;
  }

  .text-preview {
    width: 100%;
  }

  .no-preview {
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
  }
}
</style>
